package com.zjcloud.jwgl.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zjcloud.jwgl.mapper.AcLessonScheduleMapper;
import com.zjcloud.jwgl.domain.AcLessonSchedule;
import com.zjcloud.jwgl.service.IAcLessonScheduleService;
import com.zjcloud.jwgl.algorithm.GeneticScheduleAlgorithm;
import com.zjcloud.common.utils.DateUtils;

/**
 * 课程安排Service业务层处理
 * 
 * @author wxl
 * @date 2024-09-13
 */
@Service
public class AcLessonScheduleServiceImpl implements IAcLessonScheduleService 
{
    @Autowired
    private AcLessonScheduleMapper acLessonScheduleMapper;
    
    @Autowired
    private GeneticScheduleAlgorithm geneticScheduleAlgorithm;

    /**
     * 查询课程安排
     * 
     * @param id 课程安排主键
     * @return 课程安排
     */
    @Override
    public AcLessonSchedule selectAcLessonScheduleById(Long id)
    {
        return acLessonScheduleMapper.selectAcLessonScheduleById(id);
    }

    /**
     * 查询课程安排列表
     * 
     * @param acLessonSchedule 课程安排
     * @return 课程安排
     */
    @Override
    public List<AcLessonSchedule> selectAcLessonScheduleList(AcLessonSchedule acLessonSchedule)
    {
        return acLessonScheduleMapper.selectAcLessonScheduleList(acLessonSchedule);
    }

    /**
     * 新增课程安排
     * 
     * @param acLessonSchedule 课程安排
     * @return 结果
     */
    @Override
    public int insertAcLessonSchedule(AcLessonSchedule acLessonSchedule)
    {
        // 检查冲突
        Map<String, Object> conflictResult = checkConflict(acLessonSchedule);
        if ((Boolean) conflictResult.get("hasConflict")) {
            acLessonSchedule.setStatus("1"); // 设置为冲突状态
        } else {
            acLessonSchedule.setStatus("0"); // 设置为正常状态
        }
        
        acLessonSchedule.setCreateTime(DateUtils.getNowDate());
        return acLessonScheduleMapper.insertAcLessonSchedule(acLessonSchedule);
    }

    /**
     * 修改课程安排
     * 
     * @param acLessonSchedule 课程安排
     * @return 结果
     */
    @Override
    public int updateAcLessonSchedule(AcLessonSchedule acLessonSchedule)
    {
        // 检查冲突
        Map<String, Object> conflictResult = checkConflict(acLessonSchedule);
        if ((Boolean) conflictResult.get("hasConflict")) {
            acLessonSchedule.setStatus("1"); // 设置为冲突状态
        } else {
            acLessonSchedule.setStatus("0"); // 设置为正常状态
        }
        
        acLessonSchedule.setUpdateTime(DateUtils.getNowDate());
        return acLessonScheduleMapper.updateAcLessonSchedule(acLessonSchedule);
    }

    /**
     * 批量删除课程安排
     * 
     * @param ids 需要删除的课程安排主键
     * @return 结果
     */
    @Override
    public int deleteAcLessonScheduleByIds(Long[] ids)
    {
        return acLessonScheduleMapper.deleteAcLessonScheduleByIds(ids);
    }

    /**
     * 删除课程安排信息
     * 
     * @param id 课程安排主键
     * @return 结果
     */
    @Override
    public int deleteAcLessonScheduleById(Long id)
    {
        return acLessonScheduleMapper.deleteAcLessonScheduleById(id);
    }
    
    /**
     * 校验排课参数
     * 
     * @param params 排课参数
     * @throws IllegalArgumentException 如果参数无效
     */
    private void validateScheduleParams(Map<String, Object> params) {
        if (params == null) {
            throw new IllegalArgumentException("排课参数不能为空");
        }
        
        // 安全获取课程列表并验证
        Object coursesObj = params.get("courses");
        if (!(coursesObj instanceof List<?>)) {
            throw new IllegalArgumentException("课程参数格式错误，应为List类型");
        }
        List<?> coursesList = (List<?>) coursesObj;
        if (coursesList.isEmpty()) {
            throw new IllegalArgumentException("课程列表不能为空");
        }
        validateListItemType(coursesList, Long.class, "课程");
        
        // 安全获取教师列表并验证
        Object teachersObj = params.get("teachers");
        if (!(teachersObj instanceof List<?>)) {
            throw new IllegalArgumentException("教师参数格式错误，应为List类型");
        }
        List<?> teachersList = (List<?>) teachersObj;
        if (teachersList.isEmpty()) {
            throw new IllegalArgumentException("教师列表不能为空");
        }
        validateListItemType(teachersList, Long.class, "教师");
        
        // 安全获取教室列表并验证
        Object classroomsObj = params.get("classrooms");
        if (!(classroomsObj instanceof List<?>)) {
            throw new IllegalArgumentException("教室参数格式错误，应为List类型");
        }
        List<?> classroomsList = (List<?>) classroomsObj;
        if (classroomsList.isEmpty()) {
            throw new IllegalArgumentException("教室列表不能为空");
        }
        validateListItemType(classroomsList, Long.class, "教室");
        
        // 安全获取班级列表并验证
        Object classesObj = params.get("classes");
        if (!(classesObj instanceof List<?>)) {
            throw new IllegalArgumentException("班级参数格式错误，应为List类型");
        }
        List<?> classesList = (List<?>) classesObj;
        if (classesList.isEmpty()) {
            throw new IllegalArgumentException("班级列表不能为空");
        }
        validateListItemType(classesList, Long.class, "班级");
        
        // 验证学期信息
        Object semesterObj = params.get("semester");
        if (!(semesterObj instanceof String)) {
            throw new IllegalArgumentException("学期参数格式错误，应为String类型");
        }
        String semester = (String) semesterObj;
        if (semester.trim().isEmpty()) {
            throw new IllegalArgumentException("学期信息不能为空");
        }
        // 可以添加学期格式验证，例如：2023-2024-1 表示2023-2024学年第1学期
        if (!semester.matches("\\d{4}-\\d{4}-[1-2]")) {
            throw new IllegalArgumentException("学期格式不正确，应为：yyyy-yyyy-n，如：2023-2024-1");
        }
    }
    
    /**
     * 批量检查课程冲突并设置状态
     * 
     * @param scheduleList 课程安排列表
     */
    private void batchCheckConflictsAndSetStatus(List<AcLessonSchedule> scheduleList) {
        if (scheduleList == null || scheduleList.isEmpty()) {
            return;
        }
        
        for (AcLessonSchedule schedule : scheduleList) {
            Map<String, Object> conflictResult = checkConflict(schedule);
            schedule.setStatus((Boolean) conflictResult.get("hasConflict") ? "1" : "0");
        }
    }

    @Override
    @org.springframework.transaction.annotation.Transactional(rollbackFor = Exception.class)
    public List<AcLessonSchedule> generateSchedule(Map<String, Object> params) {
        try {
            // 参数校验
            validateScheduleParams(params);
            
            // 提取必要参数
            List<Long> courses = (List<Long>) params.get("courses");
            List<Long> teachers = (List<Long>) params.get("teachers");
            List<Long> classrooms = (List<Long>) params.get("classrooms");
            List<Long> classes = (List<Long>) params.get("classes");
            String semester = (String) params.get("semester");
            
            // 调用遗传算法进行排课
            List<AcLessonSchedule> scheduleResult = geneticScheduleAlgorithm.schedule(
                courses, teachers, classrooms, classes, params);
            
            if (scheduleResult == null || scheduleResult.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 设置基本信息
            java.util.Date now = DateUtils.getNowDate();
            for (AcLessonSchedule schedule : scheduleResult) {
                schedule.setSemester(semester);
                schedule.setCreateTime(now);
            }
            
            // 批量检查冲突并设置状态
            batchCheckConflictsAndSetStatus(scheduleResult);
            
            // 批量保存排课结果
            if (!scheduleResult.isEmpty()) {
                acLessonScheduleMapper.batchInsertSchedule(scheduleResult);
            }
            
            return scheduleResult;
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            org.slf4j.LoggerFactory.getLogger(this.getClass())
                .error("智能排课过程中发生错误", e);
            throw new RuntimeException("智能排课过程中发生错误: " + e.getMessage(), e);
        }
    }
    
    /**
     * 检测课程冲突
     * 
     * @param acLessonSchedule 课程安排
     * @return 冲突信息
     */
    @Override
    public Map<String, Object> checkConflict(AcLessonSchedule acLessonSchedule) {
        Map<String, Object> result = new HashMap<>();
        List<String> conflicts = new ArrayList<>();
        boolean hasConflict = false;
        
        // 检查教师时间冲突 - 优化参数传递和类型处理
        List<AcLessonSchedule> teacherConflicts = acLessonScheduleMapper.checkTeacherTimeConflict(
                acLessonSchedule.getTeacherId(), 
                String.valueOf(acLessonSchedule.getWeekDay()), 
                String.valueOf(acLessonSchedule.getLessonNo()),
                acLessonSchedule.getId());
        
        if (!teacherConflicts.isEmpty()) {
            hasConflict = true;
            conflicts.add("教师在该时间段已有其他课程安排");
        }
        
        // 检查教室时间冲突
        List<AcLessonSchedule> classroomConflicts = acLessonScheduleMapper.checkClassroomTimeConflict(
                acLessonSchedule.getClassroomId(), 
                acLessonSchedule.getWeekDay(), 
                acLessonSchedule.getLessonNo(),
                acLessonSchedule.getId());
        
        if (!classroomConflicts.isEmpty()) {
            hasConflict = true;
            conflicts.add("教室在该时间段已被占用");
        }
        
        // 检查班级时间冲突
        List<AcLessonSchedule> classConflicts = acLessonScheduleMapper.checkClassTimeConflict(
                acLessonSchedule.getClassId(), 
                acLessonSchedule.getWeekDay(), 
                acLessonSchedule.getLessonNo(),
                acLessonSchedule.getId());
        
        if (!classConflicts.isEmpty()) {
            hasConflict = true;
            conflicts.add("班级在该时间段已有其他课程安排");
        }
        
        result.put("hasConflict", hasConflict);
        result.put("conflicts", conflicts);
        result.put("teacherConflicts", teacherConflicts);
        result.put("classroomConflicts", classroomConflicts);
        result.put("classConflicts", classConflicts);
        
        return result;
    }
    
    /**
     * 验证列表中的元素类型
     * 
     * @param list 要验证的列表
     * @param expectedType 期望的元素类型
     * @param listName 列表名称（用于错误消息）
     * @throws IllegalArgumentException 如果列表中包含不符合期望类型的元素
     */
    private <T> void validateListItemType(List<?> list, Class<T> expectedType, String listName) {
        for (int i = 0; i < list.size(); i++) {
            Object item = list.get(i);
            if (item != null && !expectedType.isInstance(item)) {
                throw new IllegalArgumentException(listName + "列表中第" + (i + 1) + "个元素类型错误，应为" + expectedType.getSimpleName() + "类型");
            }
        }
    }
}